// Copyright 2011 Google Inc. All Rights Reserved.
// Author: jacobsa@google.com (Aaron Jacobs)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * A class representing a set of strings, offering efficient insertion and
 * containment testing.
 *
 * @constructor
 */
flame.internal.StringSet = function() {
  /**
   * An object whose keys are the elements of this set. This takes advantage of
   * the fact that objects are usually implemented as hash maps.
   *
   * @type{!Object}
   */
  this.elements_ = {};
};

/**
 * Insert a string into the set.
 *
 * @param {string} element
 */
flame.internal.StringSet.prototype.insert = function(element) {
  if (typeof(element) != 'string') {
    throw new TypeError('Argument must be a string.');
  }

  this.elements_[element] = true;
};

/**
 * Remove a string from the set. It is not an error for the set to not already
 * contain the string.
 *
 * @param {string} element
 */
flame.internal.StringSet.prototype.remove = function(element) {
  if (typeof(element) != 'string') {
    throw new TypeError('Argument must be a string.');
  }

  delete this.elements_[element];
};

/**
 * Test whether the set contains the given element.
 *
 * @param {string} element
 * @return {boolean}
 */
flame.internal.StringSet.prototype.contains = function(element) {
  if (typeof(element) != 'string') {
    throw new TypeError('Argument must be a string.');
  }

  // Use hasOwnProperty.call because the user may have inserted the string
  // 'hasOwnProperty' into the set.
  return Object.hasOwnProperty.call(this.elements_, element);
};

/**
 * Get a list of all elements in the set. The order is undefined.
 *
 * @return {!Array.<string>}
 */
flame.internal.StringSet.prototype.getElements = function() {
  return /** @type{!Array.<string>} */(Object.keys(this.elements_));
};
